3 * Populate ar_rev_id in pre-1.5 rows
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
21 * @ingroup Maintenance
24 use Wikimedia\Rdbms\IDatabase
;
26 require_once __DIR__
. '/Maintenance.php';
29 * Maintenance script that populares archive.ar_rev_id in old rows
31 * @ingroup Maintenance
34 class PopulateArchiveRevId
extends LoggedUpdateMaintenance
{
36 /** @var array|null Dummy revision row */
37 private static $dummyRev = null;
39 public function __construct() {
40 parent
::__construct();
41 $this->addDescription( 'Populate ar_rev_id in pre-1.5 rows' );
42 $this->setBatchSize( 100 );
45 protected function getUpdateKey() {
49 protected function doDBUpdates() {
50 $this->output( "Populating ar_rev_id...\n" );
51 $dbw = $this->getDB( DB_MASTER
);
53 // Quick exit if there are no rows needing updates.
54 $any = $dbw->selectField(
57 [ 'ar_rev_id' => null ],
61 $this->output( "Completed ar_rev_id population, 0 rows updated.\n" );
69 $arIds = $dbw->selectFieldValues(
72 [ 'ar_rev_id' => null ],
74 [ 'LIMIT' => $this->getBatchSize(), 'ORDER BY' => [ 'ar_id' ] ]
77 $this->output( "Completed ar_rev_id population, $count rows updated.\n" );
81 $count +
= self
::reassignArRevIds( $dbw, $arIds, [ 'ar_rev_id' => null ] );
85 $this->output( " ... $min-$max\n" );
90 * Assign new ar_rev_ids to a set of ar_ids.
91 * @param IDatabase $dbw
93 * @param array $conds Extra conditions for the update
94 * @return int Number of updated rows
96 public static function reassignArRevIds( IDatabase
$dbw, array $arIds, array $conds = [] ) {
97 if ( !self
::$dummyRev ) {
98 self
::$dummyRev = self
::makeDummyRevisionRow( $dbw );
101 $updates = $dbw->doAtomicSection( __METHOD__
, function ( $dbw, $fname ) use ( $arIds ) {
102 // Create new rev_ids by inserting dummy rows into revision and then deleting them.
103 $dbw->insert( 'revision', array_fill( 0, count( $arIds ), self
::$dummyRev ), $fname );
104 $revIds = $dbw->selectFieldValues(
107 [ 'rev_timestamp' => self
::$dummyRev['rev_timestamp'] ],
110 if ( !is_array( $revIds ) ) {
111 throw new UnexpectedValueException( 'Failed to insert dummy revisions' );
113 if ( count( $revIds ) !== count( $arIds ) ) {
114 throw new UnexpectedValueException(
115 'Tried to insert ' . count( $arIds ) . ' dummy revisions, but found '
116 . count( $revIds ) . ' matching rows.'
119 $dbw->delete( 'revision', [ 'rev_id' => $revIds ], $fname );
121 return array_combine( $arIds, $revIds );
125 foreach ( $updates as $arId => $revId ) {
128 [ 'ar_rev_id' => $revId ],
129 [ 'ar_id' => $arId ] +
$conds,
132 $count +
= $dbw->affectedRows();
138 * Construct a dummy revision table row to use for reserving IDs
140 * The row will have a wildly unlikely timestamp, and possibly a generic
141 * user and comment, but will otherwise be derived from a revision on the
142 * wiki's main page or some other revision in the database.
144 * @param IDatabase $dbw
147 private static function makeDummyRevisionRow( IDatabase
$dbw ) {
148 $ts = $dbw->timestamp( '11111111111111' );
151 $mainPage = Title
::newMainPage();
152 $pageId = $mainPage ?
$mainPage->getArticleId() : null;
154 $rev = $dbw->selectRow(
157 [ 'rev_page' => $pageId ],
159 [ 'ORDER BY' => 'rev_timestamp ASC' ]
164 // No main page? Let's see if there are any revisions at all
165 $rev = $dbw->selectRow(
170 [ 'ORDER BY' => 'rev_timestamp ASC' ]
174 throw new UnexpectedValueException( 'No revisions are available to copy' );
177 unset( $rev->rev_id
);
179 $rev['rev_timestamp'] = $ts;
180 if ( isset( $rev['rev_user'] ) ) {
181 $rev['rev_user'] = 0;
182 $rev['rev_user_text'] = '0.0.0.0';
184 if ( isset( $rev['rev_comment'] ) ) {
185 $rev['rev_comment'] = 'Dummy row';
188 $any = $dbw->selectField(
191 [ 'rev_timestamp' => $ts ],
195 throw new UnexpectedValueException( "... Why does your database contain a revision dated $ts?" );
202 $maintClass = "PopulateArchiveRevId";
203 require_once RUN_MAINTENANCE_IF_MAIN
;